/**
* @file Infrasound.VDM.h
*
* @ingroup libVDM
* @brief   virtual data memory implementation for complete network frames
* 
*  - segment history
*  - 512byte Blocks can be pagedto sd-card if deficient memory
*
*	use #define SDCARD 1 in your AppConf.h for nodes equipped with SD cards
* 
* @author  Andreas Schlueter <mersaultpatrice@gmail.com>
* @date    act 2008
* @version 0.1
*/

#ifndef VIRTUAL_DATA_MEMORY_H
#define VIRTUAL_DATA_MEMORY_H
#include <Network.DLL.h>
#include <ScatterWeb.System.h>

#define BLOCK_SIZE      512      ///< blocksize must be supported by sd-card

#ifdef  SENSOR
#define NUM_RAM_BLOCKS  4       ///< number of blocks in RAM (minimum 1 is used as dma buffer)
#else							///< gateway and intermediate need less
#ifdef SDCARD
#define NUM_RAM_BLOCKS  4       
#else
#define NUM_RAM_BLOCKS  4		///< no SD card increases mem needs
#endif
#endif


#define NUM_FRAMES	4		///< 4 segments per block


/**
* ERROR codes
*/
#define VDM_SUCCEEDED			0 ///< management stack or queue full
#define VDM_ERROR_OVERFLOW		1 ///< management stack or queue full
#define VDM_ERROR_SD_CARD		2 ///< sd card io error
#define VDM_ERROR_NULLPOINTER	3 ///< nullpointer exception
#define VDM_ACCESS_VIOLATION	4 ///< nullpointer exception

///< deletes frame from buffer

/**
* @brief data block of 512byte block
*		 block can be swapped to SD card
*
* @NOTE  size of entire structure must be even!
*/ 
typedef struct{
	uint16_t		num_frames:15;			///< counts the used packets in block
	uint16_t		locked:1;				///< true, if block is allocated
		
	uint16_t		sd_address:14;			///< sd card address, if block was paged
	uint16_t		dirty:1;				///< ==1, if block has changed
	uint16_t		paged:1;				///< ==i, if black has valid sd address

	frame_t		frames[NUM_FRAMES];			///< 4 segments per block - 512Bytes
}sd_block_t;

/**
* initializes dma and all RAM blocks mutexes and sd card
*
* @return 0, if success
*/
uint8_t vdm_init();

#ifdef SENSOR
/**
* @brief allocates a block
* @return a block or NULL if RAM is full
*/
sd_block_t* vdm_allocate();
#endif

/**
* @brief requests an empty block
*        the field num_frames must be maintained by application
*        before the block is released
* @return an empty or partly filled block or NULL if RAM is full
*/
sd_block_t* vdm_requestBlock();

/**
* @brief a block is released to VDM. Block can be paged, after
*
* @param b the block to be released. set the dirty bit, if frames are added and they
*          will be added to history automatically.
* @return 0, if success
*/
uint8_t vdm_releaseBlock(sd_block_t* b);


#ifdef SDCARD
/**
* @brief all full block are paged out to SD card 
* @param single if true, only one block is paged, otherwise all full blocks
*/
void vdm_pageout(bool single);

/**
* @brief reads blocks from SD card, as long as paged out blocks
*        and empty RAM blocks are available
*/
void vdm_pagein();
#endif

/**
* @brief removes frame from block and updates block management 
* @param block		block contains frame
* @param frame_idx index of frame
*/
void vdm_remove_frame(uint8_t block_idx, uint8_t frame_idx);

#ifdef VDM_DEBUG
/**
* @brief prints the sizes of all queues and stacks
*/
void vdm_printStatus();

/**
* @brief checks all management structures for valid entries
*/
void vdm_invariant(bool verbose);

#endif


#endif

